﻿using System;
using System.Collections.Generic;
using System.IO;
using AppDomainToolkit;
using ZilLion.Core.Log;
using ZilLion.Core.Unities.UnitiesMethods;
using IDisposable = System.IDisposable;

namespace ZilLion.Core.TaskManager.Client.Core
{
    public class TaskRuntimePool : IDisposable
    {
        /// <summary>
        ///     作业执行appdomain
        /// </summary>
        public readonly Dictionary<string, IAppDomainContext> AppDomainPool =
            new Dictionary<string, IAppDomainContext>();

        public void Dispose()
        {
            foreach (var moduleName in AppDomainPool.Keys)
                Remove(moduleName);
        }

        public void Add(string moduleName)
        {
            if (!AppDomainPool.ContainsKey(moduleName))
            {
                var setup = new AppDomainSetup
                {
                    ApplicationName = $"TaskRunner_{moduleName}",
                    ApplicationBase = FileHelper.GetRootPath(),
                    PrivateBinPath = "ZilLionTask",
                    CachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "JobCachePath"),
                    ShadowCopyFiles = "true",
                    
                };
                setup.ShadowCopyDirectories = string.Concat(setup.ApplicationBase, ";", setup.PrivateBinPath);
                var remoteDomain = AppDomain.CreateDomain($"{moduleName}AppDomain", null, setup);
                AppDomain.MonitoringIsEnabled = true;
                remoteDomain.UnhandledException +=
                    (s, e) => { ZilLionLogManager.GetLogger().Error(e.ExceptionObject as Exception); };
                var context = AppDomainContext.Wrap(remoteDomain);
                AppDomainPool.Add(moduleName, context);
            }
        }

        public void Remove(string moduleName)
        {
            if (AppDomainPool.ContainsKey(moduleName))
                AppDomainPool.Remove(moduleName);
        }

        public IAppDomainContext GetAppDomainContext(string moduleName)
        {
            if (AppDomainPool.ContainsKey(moduleName))
                return AppDomainPool[moduleName];
            return null;
        }

        #region 单例

        private TaskRuntimePool()
        {
        }

        private static TaskRuntimePool instance;

        public static TaskRuntimePool GetInstance()
        {
            if (instance == null) instance = new TaskRuntimePool();
            return instance;
        }

        #endregion
    }
}